using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;

using NSimpleDB.Service.Contract;

using Forum.Contracts;

namespace Forum.DataAccess
{
    public class DataAccessAdapter : IDataAccess
    {
        ISimpleDBService db;

        public DataAccessAdapter()
        {
            string filename = ConfigurationSettings.AppSettings["dataAccessAdapter.filename"];
            if (filename != null && filename != "")
                this.db = new NSimpleDB.Service.VistaDb.VistaDbSimpleDBService(filename);
            else
            {
                string accessKeyId = ConfigurationSettings.AppSettings["dataAccessAdapter.accessKeyId"];
                string secretAccessKey = ConfigurationSettings.AppSettings["dataAccessAdapter.secrectAccessKey"];
                if (accessKeyId != null && accessKeyId != "" && secretAccessKey != null && secretAccessKey != "")
                    this.db = new NSimpleDB.Service.Amazon.AmazonSimpleDBService(accessKeyId, secretAccessKey);
                else
                    throw new ConfigurationException("Missing data access configuration settings!");
            }
        }

        public DataAccessAdapter(string filename)
        {
            this.db = new NSimpleDB.Service.VistaDb.VistaDbSimpleDBService(filename);
        }

        public DataAccessAdapter(string accessKeyId, string secretAccessKey)
        {
            this.db = new NSimpleDB.Service.Amazon.AmazonSimpleDBService(accessKeyId, secretAccessKey);
        }


        #region IDataAccess Members


        public void Initialize()
        {
            this.db.CreateDomain(Mapping.Mapper.ForumsDomainName);
        }

        public void Clear()
        {
            this.db.DeleteDomain(Mapping.Mapper.ForumsDomainName);
        }


        public Posting[] FindPostingsByParent(Posting parent)
        {
            #region find posting ids
            List<string> postingIds;

            if (parent == null)
            {
                // get root postings
                postingIds = new List<string>(this.db.Query(Mapping.Mapper.ForumsDomainName, "['isRoot' = 'true']"));
            }
            else
            {
                // get postings via their parent; they are its replies
                postingIds = new List<string>();
                foreach(ISimpleDBAttribute a in this.db.GetAttributes(Mapping.Mapper.ForumsDomainName, parent.Id, "replyId"))
                    postingIds.Add(a.Value);
            }
            #endregion

            #region load postings
            DateTime s = DateTime.Now;

            Retrievers.IPostingRetriever r;
            if (this.db as NSimpleDB.Service.Amazon.AmazonSimpleDBService != null)
                //r = new Retrievers.SequentialPostingRetriever();
                r = new Retrievers.ParallelPostingRetriever();
            else
                r = new Retrievers.SequentialPostingRetriever();
            Posting[] resultset = r.Retrieve(this, this.db, parent, postingIds.ToArray());

            Console.WriteLine("{0} to retrieve postings", DateTime.Now.Subtract(s));

            return resultset;
            #endregion
        }


        public string GetPostingText(string postingId)
        {
            throw new NotImplementedException();
            //StringBuilder text = new StringBuilder("");
            //foreach(ISimpleDBAttribute a in this.db.GetAttributes(Mapping.Mapper.ForumsDomainName, postingId, "text"))
            //    text.Append(a.Value);
            //return text.ToString();
        }


        // item(subject, text*, createdAt, createdBy, [isRoot], [replyId*])
        public void StorePosting(Posting posting)
        {
            #region store posting
            this.db.PutAttributes(Mapping.Mapper.ForumsDomainName, posting.Id, Mapping.Mapper.MapPosting2Attributes(posting));
            #endregion

            #region add posting to parent
            if (posting.Parent != null)
            {
                this.db.PutAttributes(Mapping.Mapper.ForumsDomainName, posting.Parent.Id,
                                      new SimpleDBAttribute("replyId", posting.Id));
            }
            #endregion
        }
        #endregion


        #region IDisposable Members

        public void Dispose()
        {
            this.db.Close();
        }

        #endregion
    }
}
